package com.example.gm.service;

import java.time.Instant;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
import org.springframework.security.oauth2.jwt.JwsHeader;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.security.oauth2.jwt.JwtClaimsSet.Builder;
import org.springframework.stereotype.Component;

@Component
public class GmJwtService {
	@Autowired
	JwtEncoder jwtEncoder;
	@Autowired
	JwtDecoder jwtDecoder;

	long expiry = 36000L;

	public JwtClaimsSet createClaimsSet(String userid) {
		Instant now = Instant.now();
        /*
         * JWT 规定了7个官方字段
         	iss (issuer)：签发人
			exp (expiration time)：过期时间
			sub (subject)：主题
			aud (audience)：受众
			nbf (Not Before)：生效时间
			iat (Issued At)：签发时间
			jti (JWT ID)：编号
         */		
		Builder builder = JwtClaimsSet.builder()
			.issuer("self") // 签发人 = self
			.issuedAt(now) // 签发时间 = 现在
			.expiresAt(now.plusSeconds(expiry)) // 过期时间 = 36000 秒 = 10 小时
			.subject(userid);
		return builder.build();
	}
	
	public String createToken(String userid) {
		JwtClaimsSet claims = this.createClaimsSet(userid);
		if(claims==null)return null;
		//改用MAC算法生成令牌
		var encodedParameters = JwtEncoderParameters.from(JwsHeader.with(MacAlgorithm.HS256).build(), claims);
		return this.jwtEncoder.encode(encodedParameters).getTokenValue();
	}
	
	public String getUseridByToken(String token) {
		org.springframework.security.oauth2.jwt.Jwt jwt = this.jwtDecoder.decode(token);
		if(jwt==null) return null;

		Instant expire = jwt.getExpiresAt();//过期时间
		Instant now = Instant.now();//当前时间
		if(now.compareTo(expire)>0) {
			// 当前时间比过期时间大，表示已经过期
			System.out.println("令牌已经过期");
			return null;
		}else {
			return jwt.getSubject();
		}
	}

	public Authentication getUserAuth() {
		SecurityContext sc = SecurityContextHolder.getContext();
		if(sc==null)return null;
		return sc.getAuthentication();
	}

	public String getUserid() {
		Authentication authentication = this.getUserAuth();
		if(authentication==null)return null;
		return authentication.getName();
	}
}
